package com.klangner.go.app;

import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.util.Vector;

import com.klangner.game.board.IBoard;
import com.klangner.go.app.rules.BoardModel;
import com.klangner.go.app.rules.GoConstants;
import com.klangner.go.app.rules.GoGame;
import com.klangner.go.app.rules.GoGameAdapter;
import com.klangner.go.app.rules.GoGameEvent;
import com.klangner.go.app.strategy.AtariGoEstimatorCho;
import com.klangner.go.app.widget.GobanView;


public class GoApplet extends Applet implements ActionListener {

    class StartGameThread extends Thread {
        public void run() {
          game.playGame();
        }
    }

    boolean isStandalone = false;
    BorderLayout borderLayout1 = new BorderLayout();
    Panel panel1 = new Panel();
    Panel panel2 = new Panel();
    Button btnStart = new Button();
    Button btnStop = new Button();
    Panel pnlGoban = new Panel();
    BorderLayout borderLayout2 = new BorderLayout();


    //Get a parameter value
    public String getParameter(String key, String def) {
        return isStandalone ? System.getProperty(key, def) :
            (getParameter(key) != null ? getParameter(key) : def);
    }

    //Construct the applet
    public GoApplet() {
        gameManager = new GameManager();
        estimator = new AtariGoEstimatorCho();
        this.addActionListener(this);
        btnStart.addActionListener(this);
        btnStop.addActionListener(this);
    }

    //Initialize the applet
    public void init() {
        try {
            jbInit();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    //Component initialization
    private void jbInit() throws Exception {
        this.setLayout(borderLayout1);
        this.setSize(400,400);
        panel2.setLayout(borderLayout2);

        btnStart.setLabel("Start game");
        btnStart.setActionCommand(acStart);

        btnStop.setLabel("Reset");
        btnStop.setActionCommand(acReset);

        pnlGoban.setLayout(new BorderLayout());
        gobanView = new GobanView(new BoardModel(GameManagerConstants.
            AtariGoTableSize));

        btnWhiteSettings.setLabel("Setings");
        btnWhiteSettings.addActionListener(new java.awt.event.ActionListener() {
          public void actionPerformed(ActionEvent e) {
            btnWhiteSettings_actionPerformed(e);
          }
        });
        btnBlackSettings.setLabel("Settings");
        btnBlackSettings.addActionListener(new java.awt.event.ActionListener() {
          public void actionPerformed(ActionEvent e) {
            btnBlackSettings_actionPerformed(e);
          }
        });
        pnlGoban.add(gobanView, BorderLayout.CENTER);

        gridLayout1.setRows(4);
        edtBoardSize.setBackground(Color.white);
        this.add(panel1, BorderLayout.SOUTH);

        panel1.add(btnStart, null);
        panel1.add(btnStop, null);

        this.add(panel2, BorderLayout.CENTER);
        panel2.add(pnlGoban, BorderLayout.CENTER);
        panel2.add(panel5, BorderLayout.NORTH);
        panel5.add(panel4, null);
        panel4.add(label1, null);
        panel4.add(choiceBlackPlayerType, null);
        panel4.add(btnBlackSettings, null);
        panel5.add(panel3, null);
        panel3.add(label2, null);
        panel3.add(choiceWhitePlayerType, null);
        panel3.add(btnWhiteSettings, null);
        panel5.add(panel6, null);
        panel6.add(label3, null);
        panel6.add(edtBoardSize, null);
        panel5.add(panel7, null);
        panel7.add(lblStatus, null);
        panel7.add(lblStatusMessage, null);

        label2.setText("White is ");
        label3.setText("Board size");
        edtBoardSize.setText("5");
        edtBoardSize.setColumns(2);
        label1.setText("Black is ");
        gridLayout1.setColumns(1);
        panel5.setLayout(gridLayout1);
        panel4.setLayout(flowLayout2);

        lblStatusMessage.setText(smGameNotStarted);
        lblStatus.setText("Game status: ");

        choiceBlackPlayerType.addItem(GoConstants.ptAliceComputerPlayer);
        choiceBlackPlayerType.addItem(GoConstants.ptHumanPlayer);
        choiceBlackPlayerType.addItem(GoConstants.ptAlphaBetaComputerPlayer);
        choiceBlackPlayerType.select(0);

        choiceWhitePlayerType.addItem(GoConstants.ptAlphaBetaComputerPlayer);
        choiceWhitePlayerType.addItem(GoConstants.ptAliceComputerPlayer);
        choiceWhitePlayerType.addItem(GoConstants.ptHumanPlayer);
        choiceWhitePlayerType.select(0);

        whiteDialog = new SimpleSettingsFrame( GoConstants.defaultMaxDepth );
        blackDialog = new SimpleSettingsFrame( GoConstants.defaultMaxDepth );

        setControlsCanStart();
    }

    //Start the applet
    public void start() {
    }

    //Stop the applet
    public void stop() {
    }

    //Destroy the applet
    public void destroy() {
    }

    //Get Applet information
    public String getAppletInfo() {
        return "Applet Information";
    }

    //Get parameter info
    public String[][] getParameterInfo() {
        return null;
    }

    /**
     * Sets the visual controls ready to start.
     */
    void setControlsCanStart() {
        btnStart.setEnabled(true);
        btnStop.setEnabled(false);
        choiceBlackPlayerType.setEnabled(true);
        choiceWhitePlayerType.setEnabled(true);
        edtBoardSize.setEnabled(true);
    }

    /**
     * Sets the visual controls ready to stop.
     */
    void setControlsCanStop() {
        btnStop.setEnabled(true);
        btnStart.setEnabled(false);
        choiceBlackPlayerType.setEnabled(false);
        choiceWhitePlayerType.setEnabled(false);
        edtBoardSize.setEnabled(false);
    }

    /**
     * ActionListener method
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals(acStart)) {
            lblStatusMessage.setText(smBlackThinking);

            this.setVisible(true);

            setControlsCanStop();

            game = gameManager.createGame(
                Integer.parseInt(edtBoardSize.getText()),
                choiceBlackPlayerType.getSelectedItem(),
                blackDialog.getMaxDepth(),
                choiceWhitePlayerType.getSelectedItem(),
                whiteDialog.getMaxDepth() );

            gobanView.setGoPosition(game.goPosition);

            gameManager.registerGobanView(gobanView);

            game.addPriorityListener(gobanView);

            game.addPriorityListener(new GoGameAdapter() {
                public void positionChanged(GoGameEvent goGameEvent) {
                    if (estimator.checkPositionState(
                        goGameEvent.getNewPosition()) ==
                            GoConstants.InProgress ) {
                        if ( goGameEvent.getNewPosition().getTurnColor() ==
                        	IBoard.BLACK_STONE ) {
                          lblStatusMessage.setText(smBlackThinking);
                        }
                        else {
                          lblStatusMessage.setText(smWhiteThinking);
                        }
                    }
                    else if ( estimator.checkPositionState(
                                goGameEvent.getNewPosition() ) ==
                                    GoConstants.BlackWIN ) {
                        lblStatusMessage.setText(smBlackWon);
                    }
                    else if ( estimator.checkPositionState(
                                goGameEvent.getNewPosition() ) ==
                                    GoConstants.WhiteWIN ) {
                        lblStatusMessage.setText(smWhiteWon);
                    }
                }
            }); // end addListener

            gobanView.repaint();


            StartGameThread startGameThread = new StartGameThread();
            startGameThread.start();
        }
        else if (e.getActionCommand().equals(acReset)) {
            lblStatusMessage.setText(smGameNotStarted);

            gobanView.setGoPosition( new BoardModel(
                Integer.parseInt(edtBoardSize.getText() ) ) );
            gobanView.repaint();

            gameManager.unregisterGobanView(gobanView);

            setControlsCanStart();
        }
        else if (e.getActionCommand().equals(GameManagerConstants.FirstMove)) {
            //this.statusBar.setText("Go to beginning");
        }
        else if (e.getActionCommand().equals(GameManagerConstants.PrevMove)) {
            //this.statusBar.setText("Go to previous move");
        }
        else if (e.getActionCommand().equals(GameManagerConstants.NextMove)) {
            //this.statusBar.setText("Go to next move");
        }
        else if (e.getActionCommand().equals(GameManagerConstants.LastMove)) {
            //this.statusBar.setText("Go to last move");
        }
    }

    void btnWhiteSettings_actionPerformed(ActionEvent e) {
        if (choiceWhitePlayerType.getSelectedItem().equals( GoConstants.
                ptAlphaBetaComputerPlayer)) {

            whiteDialog.setVisible( true) ;
            whiteDialog.requestFocus();
        }
    }

    void btnBlackSettings_actionPerformed(ActionEvent e) {
        if (choiceBlackPlayerType.getSelectedItem().equals( GoConstants.
                ptAlphaBetaComputerPlayer)) {

            blackDialog.setVisible( true );
            blackDialog.requestFocus();
        }
    }


    protected Vector listeners = new Vector();

    public void addActionListener(ActionListener l) {
        listeners.addElement(l);
    }

    public void removeActionListener(ActionListener l) {
        listeners.removeElement(l);
    }

    //Main method
    public static void main(String[] args) {
        GoApplet applet = new GoApplet();
        applet.isStandalone = true;
        Frame frame;
        frame = new Frame() {

            protected void processWindowEvent(WindowEvent e) {
                super.processWindowEvent(e);
                if (e.getID() == WindowEvent.WINDOW_CLOSING) {
                    System.exit(0);
                }
            }

            public synchronized void setTitle(String title) {
                super.setTitle(title);
                enableEvents(AWTEvent.WINDOW_EVENT_MASK);
            }
        };
        frame.setTitle("Applet Frame");
        frame.add(applet, BorderLayout.CENTER);
        applet.init();
        applet.start();
        frame.setSize(400,420);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
        frame.setVisible(true);
    }

  private GameManager gameManager = null;
  private GoGame game = null;
  private GobanView gobanView = null;

  private AtariGoEstimatorCho estimator = null;

  /**
   * If black's strategy is a reading-ahead one, this is the limit.
   */
  private int blackStrategyMaxDepth = 1;

  /**
   * If white's strategy is a reading-ahead one, this is the limit.
   */
  private int whiteStrategyMaxDepth = 1;

  private final String acStart = "Start game";
  private final String acReset = "Reset";

  private final String smGameNotStarted = "Not started yet...";
  private final String smGameOver = "Game over!";
  private final String smBlackThinking = "Black thinking...";
  private final String smWhiteThinking = "White thinking...";
  private final String smBlackWon = "Black won!";
  private final String smWhiteWon = "White won!";


  Panel panel5 = new Panel();
  Panel panel4 = new Panel();
  FlowLayout flowLayout2 = new FlowLayout();
  GridLayout gridLayout1 = new GridLayout();
  Choice choiceBlackPlayerType = new Choice();
  Label label1 = new Label();
  TextField edtBoardSize = new TextField();
  Panel panel6 = new Panel();
  Label label3 = new Label();
  Panel panel3 = new Panel();
  Choice choiceWhitePlayerType = new Choice();
  Label label2 = new Label();
  FlowLayout flowLayout1 = new FlowLayout();
  Panel panel7 = new Panel();
  Label lblStatus = new Label();
  Label lblStatusMessage = new Label();
  Button btnWhiteSettings = new Button();
  Button btnBlackSettings = new Button();

  SimpleSettingsFrame whiteDialog = null;
  SimpleSettingsFrame blackDialog = null;
}
